package com.wtgroup.demo.leetcode.q008;

import java.util.HashMap;
import java.util.Map;

/**
 * @author dafei
 * @version 0.1
 * @date 2021/3/24 19:23
 */
public class S_MyAutomaton {

    public static void main(String[] args) {
        // String s = "42";
        // String s = "   -42";
        // String s = "words and 987";
        // String s = "4193 with words";
        // String s = "-91283472332";
        String s = "2147483648.0";
        System.out.println(new S_MyAutomaton().myAtoi(s));
    }


    /**
     * 按自己的思路实现的 1)自动机; 2)溢出判断逻辑(借助更长的long).
     *
     * @param s
     * @return
     */
    public int myAtoi(String s) {

        MyAutomaton myAutomaton = new MyAutomaton();
        return myAutomaton.read(s);
    }

    static class MyAutomaton {

        static final String S_START = "START";
        static final String S_IN_NUMBER = "IN_NUMBER";
        static final String S_SIGNED = "SIGNED";
        static final String S_END = "END";

        // static Pattern SYMBOL_SIGN = Pattern.compile("\\+|-");
        // static Pattern SYMBOL_SPACE = Pattern.compile(" ");
        // static Pattern SYMBOL_NUMBER = Pattern.compile("[0-9]");
        static final String SYMBOL_SIGN = "SIGN";
        static final String SYMBOL_SPACE = "SPACE";
        static final String SYMBOL_NUMBER = "NUMBER";
        static final String SYMBOL_OTHER = "OTHER";
        static final Map<String, Map<String, String>> stateMap;
        static {
            stateMap = new HashMap<>();
            stateMap.put(S_START, new HashMap<String, String>() {{
                put(SYMBOL_SIGN, S_SIGNED);
                put(SYMBOL_SPACE, S_START);
                put(SYMBOL_NUMBER, S_IN_NUMBER);
                put(SYMBOL_OTHER, S_END);
            }});
            stateMap.put(S_IN_NUMBER, new HashMap<String, String>() {{
                put(SYMBOL_SIGN, S_END);
                put(SYMBOL_SPACE, S_END);
                put(SYMBOL_NUMBER, S_IN_NUMBER);
                put(SYMBOL_OTHER, S_END);
            }});
            stateMap.put(S_SIGNED, new HashMap<String, String>() {{
                put(SYMBOL_SIGN, S_END);
                put(SYMBOL_SPACE, S_END);
                put(SYMBOL_NUMBER, S_IN_NUMBER);
                put(SYMBOL_OTHER, S_END);
            }});
            stateMap.put(S_END, new HashMap<String, String>() {{
                put(SYMBOL_SIGN, S_END);
                put(SYMBOL_SPACE, S_END);
                put(SYMBOL_NUMBER, S_END);
                put(SYMBOL_OTHER, S_END);
            }});
        }


        private String curState = S_START;


        public int read(String input) {

            boolean isNagtive = false; // note: 宜直接用 -1 表示
            StringBuffer numBuff = new StringBuffer();
            for (char c : input.toCharArray()) {
                this.transfer(c);
                if (this.curState == S_END) {
                    break;
                }
                switch (this.curState) {
                    case S_SIGNED:
                        isNagtive = c == '-';
                        break;
                    case S_IN_NUMBER:
                        // 积攒有效数字
                        numBuff.append(c);
                        break;
                }
            }

            // 字符串->数字
            long ans = 0;
            for (char c : numBuff.toString().toCharArray()) {
                // // 防溢出判断
                // if (this.overflowNext(ans, isNagtive, c-'0')) {
                //     return ans;
                // }

                ans = ans * 10 + (isNagtive ? -1 : 1) * (c - '0');

                if (ans <= Integer.MIN_VALUE || ans >= Integer.MAX_VALUE) {
                    return isNagtive ? Integer.MIN_VALUE : Integer.MAX_VALUE;
                }
            }


            return (int) ans;
        }

        // private boolean overflowNext(int val, boolean isNagtive, int next) {
        //     if (isNagtive) {
        //         return val < Integer.MIN_VALUE / 10 || (val == Integer.MIN_VALUE / 10 && next > 8);
        //     } else {
        //         return val > Integer.MAX_VALUE / 10 || (val == Integer.MAX_VALUE / 10 && next > 7);
        //     }
        // }

        // 接收输入=>状态
        public String transfer(char in) {
            String syb = this.parseSymbol(in);
            return this.curState = stateMap.get(this.curState).get(syb);
        }

        private String parseSymbol(char in) {
            if (in == '+' || in == '-') {
                return SYMBOL_SIGN;
            } else if(in == ' ') {
                return SYMBOL_SPACE;
            } else if (in >= '0' && in <= '9') {
                return SYMBOL_NUMBER;
            } else {
                return SYMBOL_OTHER;
            }
        }

    }
}
